package com.zlzlib.librxresult;

import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;


import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

import java.util.List;

import io.reactivex.rxjava3.annotations.Nullable;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.PublishSubject;


/**
 * @Desc: 跳转工具使用类
 * @Copyright:
 * @DateTime: 2020/9/18 9:38
 * @Author zlz
 * @Version 1.0
 */
public class RxActivityResult {
    static ActivitiesLifecycleCallbacks activitiesLifecycle;

    private RxActivityResult() {
    }

    //初始化注册监听  必须在app里面初始化
    public static void register(Application application) {
        activitiesLifecycle = new ActivitiesLifecycleCallbacks(application);
    }

    public static <T extends Activity> RxActivityResult.Builder<T> on(T activity) {
        return new RxActivityResult.Builder(activity);
    }

    public static <T extends Fragment> RxActivityResult.Builder<T> on(T fragment) {
        return new RxActivityResult.Builder(fragment);
    }

    public static class Builder<T> {
        final Class clazz;
        final PublishSubject<RxResult<T>> subject = PublishSubject.create();
        private final boolean uiTargetActivity;

        public Builder(T t) {
            if (RxActivityResult.activitiesLifecycle == null) {
                throw new IllegalStateException
                        ("You must call RxActivityResult.register(application) before attempting to use startIntent");
            } else {
                this.clazz = t.getClass();
                this.uiTargetActivity = t instanceof Activity;
            }
        }

        public Observable<RxResult<T>> startIntentSender(IntentSender intentSender, @Nullable Intent fillInIntent,
                                                         int flagsMask, int flagsValues, int extraFlags) {
            return this.startIntentSender(intentSender, fillInIntent, flagsMask, flagsValues, extraFlags, (Bundle) null);
        }

        public Observable<RxResult<T>> startIntentSender(IntentSender intentSender, @Nullable Intent fillInIntent,
                                                         int flagsMask, int flagsValues, int extraFlags, @Nullable Bundle options) {
            RequestIntentSender requestIntentSender = new RequestIntentSender(intentSender, fillInIntent,
                    flagsMask, flagsValues, extraFlags, options);
            return this.startHolderActivity(requestIntentSender, null);
        }

        public Observable<RxResult<T>> startIntent(Intent intent) {
            return this.startIntent(intent, null);
        }

        public Observable<RxResult<T>> startIntent(Intent intent, @Nullable OnPreResult onPreResult) {
            return this.startHolderActivity(new Request(intent), onPreResult);
        }

        private Observable<RxResult<T>> startHolderActivity(Request request, @Nullable OnPreResult onPreResult) {
            OnResult onResult = this.uiTargetActivity ? this.onResultActivity() : this.onResultFragment();
            request.setOnResult(onResult);
            request.setOnPreResult(onPreResult);
            HolderActivity.setRequest(request);
            RxActivityResult.activitiesLifecycle.getOLiveActivity().subscribe(activity -> {
                //65536
                activity.startActivity((new Intent(activity, HolderActivity.class)).addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION));
            });
            return this.subject;
        }

        private OnResult onResultActivity() {
            return new OnResult() {
                public void response(int requestCode, int resultCode, Intent data) {
                    if (RxActivityResult.activitiesLifecycle.getLiveActivity() != null) {
                        if (RxActivityResult.activitiesLifecycle.getLiveActivity().getClass() == Builder.this.clazz) {
                            T activity = (T) RxActivityResult.activitiesLifecycle.getLiveActivity();
                            Builder.this.subject.onNext(new RxResult(activity, requestCode, resultCode, data));
                            Builder.this.subject.onComplete();
                        }
                    }
                }

                public void error(Throwable throwable) {
                    Builder.this.subject.onError(throwable);
                }
            };
        }

        private OnResult onResultFragment() {
            return new OnResult() {
                public void response(int requestCode, int resultCode, Intent data) {
                    if (RxActivityResult.activitiesLifecycle.getLiveActivity() != null) {
                        Activity activity = RxActivityResult.activitiesLifecycle.getLiveActivity();
                        FragmentActivity fragmentActivity = (FragmentActivity) activity;
                        FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
                        Fragment targetFragment = Builder.this.getTargetFragment(fragmentManager.getFragments());
                        if (targetFragment != null) {
                            Builder.this.subject.onNext(new RxResult(targetFragment, requestCode, resultCode, data));
                            Builder.this.subject.onComplete();
                        }

                    }
                }

                public void error(Throwable throwable) {
                    Builder.this.subject.onError(throwable);
                }
            };
        }

        @Nullable
        Fragment getTargetFragment(List<Fragment> fragments) {
            if (fragments == null) {
                return null;
            } else {
                for (Fragment fragment : fragments) {
                    if (fragment != null && fragment.isVisible() && fragment.getClass() == this.clazz) {
                        return fragment;
                    }
                    if (fragment != null && fragment.isAdded()) {
                        List<Fragment> childFragments = fragment.getChildFragmentManager().getFragments();
                        Fragment candidate = this.getTargetFragment(childFragments);
                        if (candidate != null) {
                            return candidate;
                        }
                    }
                }
                return null;
            }
        }
    }
}
